home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / SpriteFight 2002 v2.0a1 / Pong.c < prev    next >
Text File  |  1996-05-01  |  11KB  |  527 lines

  1. // This is a minor hack of ...
  2. /*            pong.c
  3.  The classic game of pong in Megamax C for the Mac.
  4.  Thanks to MacTutor (Vol 1, No. 5 April 1985 page 39) for 
  5.  animation techniques. If you are reading this and don't  
  6.  subscribe to MacTutor, consider it. No resource file is  
  7.  needed. This program, source and object, is in the
  8.  public domain and not for sale. 
  9.   
  10.  Author :    David L. O'Connor, 370 Eden St. Buffalo, N.Y. 
  11.             14220.  (716) 828-0898.   CIS - 70265,1172 
  12.  Date   :    July, 1985   Version 2 
  13. */
  14. // It had to be modified in order to compile on current Macs.
  15.  
  16. #ifndef _OSUTILS_
  17. #include <OSUtils.h>
  18. #endif
  19.  
  20. /* the game diRections */
  21. #define    STOPPED 0
  22. #define    UP 1
  23. #define    DOWN 2
  24. #define    LEFT 3
  25. #define    RIGHT 4
  26. #define    UP_LEFT 5
  27. #define    UP_RIGHT 6
  28. #define    DOWN_LEFT 7
  29. #define    DOWN_RIGHT 8
  30.  
  31. #define DIFFICULTY    2
  32.  
  33. /* paddle + ball dimensions */
  34. #define    PADWIDTH 10
  35. #define    PADLENGTH 45
  36. #define    PADINSET 10
  37. #define    BALLWIDTH 9
  38. #define    BALLLENGTH 9
  39.  
  40. #define    PADDLESPEED 9
  41. #define    HIGHSCORE 20
  42.  
  43. /* from the MAC's standard pattern list */
  44. #define    PAD_PAT        qd.dkGray
  45. #define    WALL_PAT    qd.ltGray
  46.  
  47. typedef struct {
  48.     Rect r;
  49.     int dir;
  50.     int speed;
  51.     int score;
  52.     } paddle;
  53.     
  54. typedef struct {
  55.     RgnHandle    Rgn;
  56.     RgnHandle    oldRgn;
  57.     RgnHandle    unRgn;
  58.     int dir;
  59.     int speed;
  60.     int on;
  61.     } target;
  62.  
  63. paddle l_paddle, r_paddle;
  64. target ball;
  65. WindowPtr gamewindow, which_window;
  66. Rect r, top_wall, bottom_wall;
  67. EventRecord gameEvent;
  68. MenuHandle gamemenu[5];
  69. char menutitle[1];
  70. int done, paused, last_won, volleys, sound_on;
  71. short BALLSPEED  = 1;
  72. Str255 title = { 65,
  73.                         ' ',' ',' ',' ',' ',' ',' ',' ',
  74.                         'Y','o','u',':',' ',' ',' ','0',
  75.                         ' ',' ',' ',' ',' ',' ',' ',' ',
  76.                         ' ',' ',' ','H','i','d','d','e',
  77.                         'n',' ','P','o','n','g',' ','G',
  78.                         'a','m','e',' ',' ',' ',' ',' ',
  79.                         ' ',' ',' ',' ',' ',' ',' ',' ',
  80.                         'M','a','c',':',' ',' ',' ','0',
  81.                         ' ',' ',' ',' ',' ',' ',' ',' ', 
  82.                         '\0'};
  83.  
  84. HiddenPongGame(WindowPtr parentWindow) 
  85. {
  86.     SysEnvRec    theSystem;
  87.     
  88.     // Check current system info
  89.     if(SysEnvirons(curSysEnvVers, &theSystem) == noErr)
  90.     {
  91.         switch(theSystem.processor)
  92.         {
  93.             case env68000:
  94.                 BALLSPEED = 7;
  95.                 break;
  96.             case env68010:
  97.                 BALLSPEED = 6;
  98.                 break;
  99.             case env68020:
  100.                 #if defined(powerc) || defined(__powerc)
  101.                 BALLSPEED = 1; // Power PC 60x
  102.                 #else 
  103.                 BALLSPEED = 5; // it's a real MC68020
  104.                 #endif
  105.                 break;
  106.             case env68030:
  107.                 BALLSPEED = 4;
  108.                 break;
  109.             case env68040:
  110.                 BALLSPEED = 2;
  111.                 break;
  112.             case envCPUUnknown: // must be newer than PowerPC. Cool!
  113.                 BALLSPEED = 1;
  114.                 break;
  115.         }
  116.     }
  117.     
  118.     gamewindow = parentWindow;
  119.     setup();
  120.     while (! done){
  121.         Handle_Events();
  122.         play_pong();
  123.     }
  124.     FlushEvents(everyEvent, 0);
  125.     InvalRect(&gamewindow->portRect);
  126. }
  127.  
  128. setup()
  129. {
  130.     done = 0;
  131.     sound_on = 1;
  132.     last_won = RIGHT;
  133.     FlushEvents(everyEvent, 0);
  134.     SetWTitle(gamewindow, title);
  135.     SetPort(gamewindow);
  136.     EraseRect(&gamewindow->portRect);
  137.     create_l_paddle();
  138.     create_r_paddle();
  139.     create_walls();
  140.     create_ball();
  141.     Init_game();
  142. }
  143.  
  144. /* pretty much straight from SAMP in I.M. */
  145. Handle_Events()
  146. {
  147.     SystemTask();
  148.     if (GetNextEvent(everyEvent, &gameEvent))
  149.     {
  150.         switch (gameEvent.what)
  151.         {
  152.             case mouseDown :
  153.                 done = TRUE;
  154.             break;
  155.             case updateEvt :
  156.                 SetPort(gamewindow);
  157.                 BeginUpdate(gamewindow);
  158.                 FillRect(&l_paddle.r, &PAD_PAT);
  159.                 FillRect(&r_paddle.r, &PAD_PAT);
  160.                 FillRect(&top_wall, &WALL_PAT);
  161.                 FillRect(&bottom_wall, &WALL_PAT);
  162.                 if (ball.on)
  163.                     PaintRgn(ball.Rgn);
  164.                 EndUpdate(gamewindow);
  165.             break;
  166.         }
  167.     }
  168. }
  169.  
  170. play_pong()
  171. {
  172.     if (!paused)
  173.     {
  174.         if (! ball.on)
  175.             serve_ball();
  176.         check_status();
  177.         move_left_paddle();
  178.         move_right_paddle();
  179.         move_ball();
  180.     }
  181.     if(l_paddle.score > HIGHSCORE || r_paddle.score > HIGHSCORE)
  182.         done = TRUE;
  183. }
  184.  
  185. create_l_paddle()
  186. {    
  187.     l_paddle.dir = STOPPED;
  188.     l_paddle.speed = PADDLESPEED;
  189.     l_paddle.score = 0;
  190.     SetRect (&l_paddle.r, 
  191.             gamewindow->portRect.left + PADINSET,
  192.             gamewindow->portRect.top + PADINSET,
  193.             gamewindow->portRect.left + PADINSET + PADWIDTH,
  194.             gamewindow->portRect.top + PADINSET + PADLENGTH);
  195.     FillRect(&l_paddle.r, &PAD_PAT);
  196. }
  197.  
  198. create_r_paddle()
  199. {    
  200.     r_paddle.dir = STOPPED;
  201.     r_paddle.speed = PADDLESPEED;
  202.     r_paddle.score = 0;
  203.     SetRect (&r_paddle.r,
  204.             gamewindow->portRect.right - PADWIDTH - PADINSET,
  205.             gamewindow->portRect.top + PADINSET,
  206.             gamewindow->portRect.right - PADWIDTH - PADINSET + PADWIDTH,
  207.             gamewindow->portRect.top + PADINSET + PADLENGTH);
  208.     FillRect(&r_paddle.r, &PAD_PAT);    
  209. }    
  210.  
  211. create_walls()
  212. {
  213.     SetRect(&top_wall,
  214.             gamewindow->portRect.left + 20,
  215.             gamewindow->portRect.top + 5,
  216.             gamewindow->portRect.right - 20, 
  217.             gamewindow->portRect.top + 20);
  218.     FillRect(&top_wall, &WALL_PAT);
  219.     SetRect(&bottom_wall,
  220.             gamewindow->portRect.left + 20,
  221.             gamewindow->portRect.bottom - 20,
  222.             gamewindow->portRect.right - 20,
  223.             gamewindow->portRect.bottom - 5);
  224.     FillRect(&bottom_wall, &WALL_PAT);    
  225. }
  226.  
  227. create_ball()
  228. {
  229.     ball.Rgn = NewRgn();
  230.     ball.oldRgn = NewRgn();
  231.     ball.unRgn = NewRgn();
  232.     ball.dir = LEFT;
  233.     ball.speed = BALLSPEED;
  234.     SetRect (&r, 250,  150, 250 + BALLWIDTH, 150 + BALLLENGTH);
  235.     OpenRgn();
  236.     FrameOval(&r);
  237.     CloseRgn(ball.Rgn);
  238. }
  239.  
  240. serve_ball()
  241. {
  242.     register i;
  243.  
  244.     OffsetRgn(ball.Rgn, 250 - ((**ball.Rgn).rgnBBox.right),
  245.                         150 - ((**ball.Rgn).rgnBBox.top) );
  246.     for (i = 0; i < 250; i++){
  247.         check_status();
  248.         move_right_paddle();
  249.         move_left_paddle();
  250.         move_ball();
  251.     }
  252.     ball.dir = (last_won == RIGHT) ? LEFT : RIGHT;
  253.     ball.speed = BALLSPEED;
  254.     ball.on = 1;
  255.     PaintRgn(ball.Rgn);
  256. }
  257.  
  258. /* someone scored a point */
  259. kill_ball()
  260. {
  261.     ball.on = volleys = 0;
  262.     CopyRgn(ball.Rgn, ball.unRgn);
  263.     EraseRgn(ball.Rgn);
  264.     recover_from_collision();
  265.     display_score();
  266. }
  267.  
  268. Init_game()
  269. {
  270.     l_paddle.score = r_paddle.score = 0;
  271.     ball.speed = BALLSPEED;
  272.     kill_ball();
  273. }
  274.  
  275. /* check for bounces, diRection changes, scoring, etc */
  276. check_status()
  277. {
  278.     static Rect *ball_r;
  279.  
  280.     register ball_top        = (**ball.Rgn).rgnBBox.top;
  281.     register ball_bottom    = (**ball.Rgn).rgnBBox.bottom;
  282.     register ball_left        = (**ball.Rgn).rgnBBox.left;
  283.     register ball_right        = (**ball.Rgn).rgnBBox.right;
  284.     
  285.     ball_r = &((**ball.Rgn).rgnBBox);
  286.  
  287.     /* make it a little harder as time goes by */
  288.     if (volleys > 35)
  289.         ball.speed = BALLSPEED + 6;
  290.     else if (volleys > 30)
  291.         ball.speed = BALLSPEED + 5;
  292.     else if (volleys > 25)
  293.         ball.speed = BALLSPEED + 4;
  294.     else if (volleys > 20)
  295.         ball.speed = BALLSPEED + 3;
  296.     else if (volleys > 15)
  297.         ball.speed = BALLSPEED + 2;
  298.     else if (volleys > 10)
  299.         ball.speed = BALLSPEED + 1;
  300.         
  301.     r_paddle.speed = ball.speed + 2;
  302.         
  303.     /* the right paddle tries to track the ball */
  304.     if ( (ball_right > 250) &&
  305.          (ball.dir == UP_RIGHT || ball.dir == DOWN_RIGHT || 
  306.           ball.dir == RIGHT) ){
  307.         if (ball_top + handicap() < r_paddle.r.top)
  308.             r_paddle.dir = UP;
  309.         else if (ball_bottom - handicap() > r_paddle.r.bottom)
  310.             r_paddle.dir = DOWN;
  311.         else
  312.             r_paddle.dir = STOPPED;
  313.     }
  314.     else
  315.         r_paddle.dir = STOPPED;
  316.         
  317.     /* the ball and the left boundry */
  318.     if (ball_left < l_paddle.r.right ){
  319.         if (SectRect(ball_r, &l_paddle.r, &r)){
  320.             volleys++;
  321.             if (ball_top <= l_paddle.r.top + 15)
  322.                 ball.dir = UP_RIGHT;
  323.             else if (ball_top > l_paddle.r.top + 15 && ball_bottom < l_paddle.r.top + 30)
  324.                 ball.dir = RIGHT;
  325.             else
  326.                 ball.dir = DOWN_RIGHT;
  327.         }
  328.         else{
  329.             last_won = RIGHT;
  330.             r_paddle.score++;
  331.             kill_ball();
  332.         }
  333.         return;
  334.     }
  335.     
  336.     /* the ball and the right boundry */
  337.     if (ball_right > r_paddle.r.left){
  338.         if (SectRect(ball_r, &r_paddle.r, &r)){
  339.             volleys++;
  340.             if (ball_top <= r_paddle.r.top + 15)
  341.                 ball.dir = UP_LEFT;
  342.             else if (ball_top > r_paddle.r.top + 15 && ball_bottom < r_paddle.r.top + 30)
  343.                 ball.dir = LEFT;
  344.             else
  345.                 ball.dir = DOWN_LEFT;
  346.         }
  347.         else{
  348.             last_won = LEFT;
  349.             l_paddle.score++;
  350.             kill_ball();
  351.         }
  352.         return;
  353.     }
  354.     
  355.     /* the ball and the top wall */
  356.     if (ball_top < top_wall.bottom){
  357.         if (ball.dir == UP_LEFT)
  358.             ball.dir = DOWN_LEFT;
  359.         else if (ball.dir == UP_RIGHT)
  360.             ball.dir = DOWN_RIGHT;
  361.         return;
  362.     }
  363.     
  364.     /* the ball and the bottom wall */
  365.     if (ball_bottom > bottom_wall.top){
  366.         if (ball.dir == DOWN_LEFT)
  367.             ball.dir = UP_LEFT;
  368.         else if (ball.dir == DOWN_RIGHT)
  369.             ball.dir = UP_RIGHT;
  370.         return;
  371.     }
  372. }
  373.  
  374. /* the ball eats the walls and paddles */
  375. recover_from_collision()
  376. {
  377.     register Rect *rp = &((**ball.unRgn).rgnBBox);
  378.  
  379.     if (SectRect(rp, &top_wall, &r))
  380.         FillRect(&r, &WALL_PAT);
  381.     else if (SectRect(rp, &bottom_wall, &r))
  382.         FillRect(&r, &WALL_PAT);
  383.     if (SectRect(rp, &l_paddle.r, &r))
  384.         FillRect(&r, &PAD_PAT);
  385.     else if (SectRect(rp, &r_paddle.r, &r))
  386.         FillRect(&r, &PAD_PAT);
  387. }
  388.  
  389. move_left_paddle()
  390. {
  391.     static Point mouseloc;
  392.     register int newtop, newbottom;
  393.  
  394.     GetMouse(&mouseloc);
  395.     if (mouseloc.v != l_paddle.r.top){
  396.         r.left = l_paddle.r.left;
  397.         r.right = l_paddle.r.right;
  398.         if (mouseloc.v <= gamewindow->portRect.top){
  399.             newtop = gamewindow->portRect.top;
  400.             newbottom = newtop + PADLENGTH;
  401.         }
  402.         else if (mouseloc.v + PADLENGTH >= gamewindow->portRect.bottom){
  403.             newbottom = gamewindow->portRect.bottom;
  404.             newtop = newbottom - PADLENGTH;
  405.         }
  406.         else{
  407.             newtop = mouseloc.v;
  408.             newbottom = newtop + PADLENGTH;
  409.         }
  410.         if (newtop > l_paddle.r.top){
  411.             r.top = l_paddle.r.top;
  412.             r.bottom = (newtop > l_paddle.r.bottom) ? l_paddle.r.bottom : newtop;
  413.         }
  414.         else if (newtop < l_paddle.r.top){
  415.             r.bottom = l_paddle.r.bottom;
  416.             r.top = (newbottom < l_paddle.r.top) ? l_paddle.r.top : newbottom;
  417.         }
  418.         l_paddle.r.top = newtop;
  419.         l_paddle.r.bottom = newbottom;
  420.         EraseRect(&r); 
  421.         FillRect(&l_paddle.r, &PAD_PAT);
  422.     }
  423.     else
  424.         FillRect(&l_paddle.r, &PAD_PAT);
  425. }
  426.  
  427. move_right_paddle()
  428. {
  429.     if (r_paddle.dir == STOPPED)
  430.         FillRect(&r_paddle.r, &PAD_PAT);
  431.     else{
  432.         r.left = r_paddle.r.left;
  433.         r.right = r_paddle.r.right;
  434.         switch (r_paddle.dir){
  435.             case UP:
  436.                 r.bottom = r_paddle.r.bottom;
  437.                 r_paddle.r.top -= r_paddle.speed;
  438.                 r_paddle.r.bottom -= r_paddle.speed;
  439.                 r.top = r_paddle.r.bottom;
  440.             break;
  441.             case DOWN:
  442.                 r.top = r_paddle.r.top;
  443.                 r_paddle.r.top += r_paddle.speed;
  444.                 r_paddle.r.bottom += r_paddle.speed;
  445.                 r.bottom = r_paddle.r.top;
  446.             break;    
  447.         }
  448.         EraseRect(&r); 
  449.         FillRect(&r_paddle.r, &PAD_PAT);
  450.     }
  451. }
  452.  
  453. move_ball()
  454. {
  455.     if (ball.on){
  456.         CopyRgn(ball.Rgn, ball.oldRgn);
  457.         switch (ball.dir){
  458.             case LEFT:
  459.                 OffsetRgn(ball.Rgn, -ball.speed, 0);
  460.             break;
  461.             case RIGHT:
  462.                 OffsetRgn(ball.Rgn, ball.speed, 0);
  463.             break;
  464.             case UP_LEFT:
  465.                 OffsetRgn(ball.Rgn, -ball.speed, -ball.speed);
  466.             break;
  467.             case UP_RIGHT:
  468.                 OffsetRgn(ball.Rgn, ball.speed, -ball.speed);
  469.             break;
  470.             case DOWN_LEFT:
  471.                 OffsetRgn(ball.Rgn, -ball.speed, ball.speed);
  472.             break;
  473.             case DOWN_RIGHT:
  474.                 OffsetRgn(ball.Rgn, ball.speed, ball.speed);
  475.             break;
  476.         }
  477.         UnionRgn(ball.Rgn, ball.oldRgn, ball.unRgn);
  478.         DiffRgn(ball.unRgn, ball.Rgn, ball.unRgn);
  479.         EraseRgn(ball.unRgn);
  480.         PaintRgn(ball.Rgn);
  481.         recover_from_collision();
  482.     }
  483. }
  484.  
  485. display_score()
  486. {
  487.     static long i;
  488.     
  489.             i = l_paddle.score;
  490.             title[15]=0x30+(i/100);
  491.             title[16]=0x30+((i%100)/10);
  492.             title[17]=0x30+(i%10);
  493.             i = r_paddle.score;
  494.             title[63]=0x30+(i/100);
  495.             title[64]=0x30+((i%100)/10);
  496.             title[65]=0x30+(i%10);
  497.         SetWTitle(gamewindow, title);
  498. }
  499.  
  500. /* Every so often, let the Mac's paddle fail to track the ball until
  501.    the ball has passed it by a certain amount.
  502.    This is the heart of a satisfying game. */
  503. int handicap()
  504. {
  505.     register mac_skill;
  506.     int skill_level = DIFFICULTY; 
  507.  
  508.     switch(skill_level){
  509.         case 1 :
  510.             mac_skill = 2;
  511.         break;
  512.         case 2 :
  513.             mac_skill = 8;
  514.         break;
  515.         case 3 :
  516.             mac_skill = 27;
  517.         break;
  518.         case 4 :
  519.             mac_skill = 64;
  520.         break;
  521.         default :
  522.             mac_skill = 2;
  523.         break;
  524.     }
  525.     return ((Random() % mac_skill) == 0) ? 5 : 0;
  526. }
  527.